home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Jumpstart / Multimedia Microsoft Jumpstart Version 1.1a (Microsoft).BIN / develpmt / source / trans / tblt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-12  |  10.7 KB  |  413 lines

  1. /*----------------------------------------------------------------------------*\
  2. |   transparent bitmap and DIB routines.
  3. |
  4. |   in this 'C' you can find the following functions.
  5. |
  6. |       MaskBlt()               - draw a bitmap through a mono mask.
  7. |       TransBlt()              - draw a bitmap with one color transparent.
  8. |       TransStretchDIBits()    - draw a dib with one color transparent.
  9. |
  10. |   these functions take advantage of the display driver, if it supports
  11. |   transparent operations.
  12. |
  13. |
  14. |       - ToddLa
  15. |
  16. \*----------------------------------------------------------------------------*/
  17.  
  18. #include <windows.h>
  19.  
  20. #ifndef C1_TRANSPARENT
  21.     #define CAPS1           94          /* other caps */
  22.     #define C1_TRANSPARENT  0x0001      /* new raster cap */
  23.     #define TRANSPARENT1  3           /* use with SetBkMode() */
  24. #endif  /* ifndef C1_TRANSPARENT */
  25.  
  26. #define DSna 0x00220326L
  27. #define DSa  0x008800C6L
  28. #define DSo  0x00EE0086L
  29. #define DSx  0x00660046L
  30.  
  31. #define rgbBlack RGB(0,0,0)
  32. #define rgbWhite RGB(255,255,255)
  33.  
  34. #define RGBQ(rgb)   RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb))
  35.  
  36. //
  37. // MaskBlt
  38. //
  39. // use this for a true mask blt
  40. //
  41. void TrueMaskBlt (HDC hdcD,int x,int y,int dx,int dy,HDC hdcS,HDC hdcMask,int x0,int y0)
  42. {
  43.     COLORREF rgbBk,rgbFg;
  44.  
  45.     rgbBk = SetBkColor(hdcD,rgbWhite);
  46.     rgbFg = SetTextColor(hdcD,rgbBlack);
  47.  
  48.     BitBlt(hdcD,x,y,dx,dy,hdcS,   x0,y0,DSx);
  49.     BitBlt(hdcD,x,y,dx,dy,hdcMask,x0,y0,DSa);
  50.     BitBlt(hdcD,x,y,dx,dy,hdcS,   x0,y0,DSx);
  51.  
  52.     SetBkColor(hdcD,rgbBk);
  53.     SetTextColor(hdcD,rgbFg);
  54. }
  55.  
  56. //
  57. // TransMaskBlt
  58. //
  59. // use this for a mask blt where the source (hdcS) has black (ie 0)
  60. // every where the mask has white (ie 1)
  61. //
  62. void TransMaskBlt (HDC hdcD,int x,int y,int dx,int dy,HDC hdcS,HDC hdcMask,int x0,int y0)
  63. {
  64.     COLORREF rgbBk,rgbFg;
  65.  
  66.     rgbBk = SetBkColor(hdcD,rgbWhite);
  67.     rgbFg = SetTextColor(hdcD,rgbBlack);
  68.  
  69.     BitBlt(hdcD,x,y,dx,dy,hdcMask,x0,y0,DSa);
  70.     BitBlt(hdcD,x,y,dx,dy,hdcS,   x0,y0,DSo);
  71.  
  72.     SetBkColor(hdcD,rgbBk);
  73.     SetTextColor(hdcD,rgbFg);
  74. }
  75.  
  76. //
  77. // MakeMonoMask
  78. //
  79. // builds a transparent mask that you can use to draw (using TransMaskBlt)
  80. // the given bitmap causing the given color to be transparent
  81. //
  82. HBITMAP MakeTransMask(HBITMAP hbm, HPALETTE hpal, COLORREF rgb)
  83. {
  84.     HDC     hdcS;
  85.     HDC     hdc=NULL;
  86.     HBITMAP    hbmMask=NULL;
  87.     HDC     hdcMask=NULL;
  88.     BITMAP      bm;
  89.     int         dx,dy;
  90.  
  91.     GetObject(hbm, sizeof(bm), &bm);
  92.     dx = bm.bmWidth;
  93.     dy = bm.bmHeight;
  94.  
  95.     hdcS = GetDC(NULL);
  96.     hdcMask = CreateCompatibleDC(hdcS);
  97.     hdc = CreateCompatibleDC(hdcS);
  98.     ReleaseDC(NULL, hdcS);
  99.  
  100.     if (!hdc || !hdcMask)
  101.     goto exit;
  102.  
  103.     SelectObject(hdc, hbm);
  104.  
  105.     if (hpal)
  106.     {
  107.         SelectPalette(hdc, hpal, FALSE);
  108.         RealizePalette(hdc);
  109.  
  110.         SelectPalette(hdcMask, hpal, FALSE);
  111.         RealizePalette(hdcMask);
  112.     }
  113.  
  114.     //
  115.     // use upper left corner as transparent color.
  116.     //
  117.     if (rgb == (COLORREF)-1)
  118.         rgb = GetPixel(hdc, 0, 0) | 0x02000000; //!!!make a PALETTERGB()
  119.  
  120.     //
  121.     // create a mask bitmap and associated DC
  122.     //
  123.     hbmMask = CreateBitmap(dx, dy, 1, 1, NULL);
  124.  
  125.     if (!hbmMask)
  126.     goto exit;
  127.  
  128.     SelectObject(hdcMask, hbmMask);
  129.  
  130.     // do a color to mono bitblt to build the mask
  131.     // generate 1's where the source is equal to the background, else 0's
  132.  
  133.     SetBkColor(hdc, rgb);
  134.     BitBlt(hdcMask, 0, 0, dx, dy, hdc, 0, 0, SRCCOPY);
  135.  
  136.     // make all background pixels in the source BLACK
  137.  
  138.     SetBkColor(hdc,rgb);
  139.     BitBlt(hdc,0,0,dx,dy,hdcMask,0,0,DSx);
  140.  
  141. exit:
  142.     if (hdcMask)
  143.     DeleteDC(hdcMask);
  144.  
  145.     if (hdc)
  146.     DeleteDC(hdc);
  147.  
  148.     return hbmMask;
  149. }
  150.  
  151. //
  152. // TransBlt
  153. //
  154. // Transparent bitblt that uses the current
  155. // background color of the DC as the transparent color.
  156. //
  157. BOOL TransBlt(HDC hdcD,int x,int y,int dx,int dy,HDC hdcS,int x0,int y0)
  158. {
  159.     DWORD       rgbBk,rgbFg;
  160.     DWORD       rgbBkS;
  161.     HBITMAP     hbmMask;
  162.     HDC         hdcMask;
  163.     HBITMAP     hbmT;
  164.     BOOL        f = FALSE;
  165.  
  166.     //
  167.     // see if the device supports this call directly
  168.     //
  169.     // otherwise we need to simulate it.
  170.     //
  171. #ifndef WIN32
  172.     if (GetDeviceCaps(hdcD, CAPS1) & C1_TRANSPARENT)
  173.     {
  174.         WORD w;
  175.         w = SetBkMode(hdcD, TRANSPARENT1);
  176.         f = BitBlt(hdcD,x,y,dx,dy,hdcS,x0,y0,SRCCOPY);
  177.         SetBkMode(hdcD, w);
  178.         return f;
  179.     }
  180. #endif
  181.  
  182.     //
  183.     //  Get the current DC color's
  184.     //
  185.     rgbBk = GetBkColor(hdcD);
  186.     rgbFg = GetTextColor(hdcD);
  187.     rgbBkS= GetBkColor(hdcS);
  188.  
  189.     SetTextColor(hdcD,rgbBlack);
  190.  
  191.     //
  192.     //  make a memory DC for use in color conversion
  193.     //
  194.     hdcMask = CreateCompatibleDC(hdcS);
  195.  
  196.     if (!hdcMask)
  197.         return FALSE;
  198.  
  199.     //
  200.     // create a mask bitmap and associated DC
  201.     //
  202.     hbmMask = CreateBitmap(dx, dy, 1, 1, NULL);
  203.  
  204.     if (!hbmMask)
  205.         goto errorDC;
  206.  
  207.     // select the mask bitmap into the mono DC
  208.  
  209.     hbmT = (HBITMAP)SelectObject(hdcMask, hbmMask);
  210.  
  211.     // do a color to mono bitblt to build the mask
  212.     // generate 1's where the source is equal to the background, else 0's
  213.  
  214.     SetBkColor(hdcS, rgbBk);
  215.     BitBlt(hdcMask, 0, 0, dx, dy, hdcS, x0, y0, SRCCOPY);
  216.  
  217. //
  218. // The first solution (using 4 blt's) does not flicker as much as the
  219. // second (3 Blt's) solution, but is slower!
  220. //
  221. #if 0
  222.     // make all background pixels in the source BLACK
  223.  
  224.     SetBkColor(hdcS,rgbBk);
  225.     BitBlt(hdcS,x0,y0,dx,dy,hdcMask,0,0,DSx);
  226.  
  227.     // do two bitblts to draw the image w/transparent mask
  228.  
  229.     SetBkColor(hdcD,rgbWhite);
  230.     BitBlt(hdcD,x,y,dx,dy,hdcMask,0,0,DSa);
  231.     BitBlt(hdcD,x,y,dx,dy,hdcS,x0,y0,DSx);
  232.  
  233.     // restore all background pixels in the source
  234.  
  235.     SetBkColor(hdcS,rgbBk);
  236.     BitBlt(hdcS,x0,y0,dx,dy,hdcMask,0,0,DSx);
  237. #else
  238.     // do a MaskBlt to copy the bitmap to the dest
  239.  
  240.     SetBkColor(hdcD,rgbWhite);
  241.     BitBlt(hdcD,x,y,dx,dy,hdcS,   x0,y0,DSx);
  242.     BitBlt(hdcD,x,y,dx,dy,hdcMask,0 ,0 ,DSa);
  243.     BitBlt(hdcD,x,y,dx,dy,hdcS,   x0,y0,DSx);
  244. #endif
  245.  
  246.     f = TRUE;
  247.  
  248.     SelectObject(hdcMask, hbmT);
  249.     DeleteObject(hbmMask);
  250.  
  251.     //
  252.     // Restore the DC colors
  253.     //
  254.     SetBkColor(hdcS,rgbBkS);
  255.     SetBkColor(hdcD,rgbBk);
  256.     SetTextColor(hdcD,rgbFg);
  257.  
  258. errorDC:
  259.     DeleteDC(hdcMask);
  260.     return f;
  261. }
  262.  
  263.  
  264. //
  265. // draw a DIB bitmap treating the background color of the DC as transparent
  266. //
  267. int TransStretchDIBits(HDC hdc,
  268.                        WORD DstX, WORD DstY, WORD DstDX, WORD DstDY,
  269.                        WORD SrcX, WORD SrcY, WORD SrcDX, WORD SrcDY,
  270.                        LPVOID lpBits, LPBITMAPINFO lpbi,
  271.                        WORD wUsage, DWORD rop)
  272. {
  273.     struct {
  274.         BITMAPINFOHEADER    bih;
  275.         WORD                aw[256];
  276.     }   biPal;
  277.  
  278.     struct {
  279.         BITMAPINFOHEADER    bih;
  280.         DWORD               argb[256];
  281.     }   biRgb;
  282.  
  283.     WORD    FAR *pw;
  284.     DWORD   FAR *prgb;
  285.     COLORREF rgbBk;
  286.     HPALETTE hpal;
  287.     WORD     wPalBk;
  288.     WORD     wPalBlack;
  289.     WORD     wPalWhite;
  290.     int      i;
  291.  
  292.     //
  293.     // see if the device supports this call directly
  294.     //
  295.     // otherwise we need to simulate it.
  296.     //
  297. #ifndef WIN32
  298.     if (GetDeviceCaps(hdc, CAPS1) & C1_TRANSPARENT)
  299.     {
  300.         WORD w;
  301.         BOOL f;
  302.  
  303.         w = SetBkMode(hdc, TRANSPARENT1);
  304.  
  305.         f = StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
  306.                               SrcX,SrcY,SrcDX,SrcDY,
  307.                               lpBits, lpbi, wUsage, rop);
  308.         SetBkMode(hdc, w);
  309.         return f;
  310.     }
  311. #endif
  312.  
  313.     //
  314.     //  we want to do the equivelent of a MaskBlt, but we dont have to
  315.     //  create multiple masks and things, we just change the color
  316.     //  table of DIB, (aren't DIBs great)
  317.     //
  318.     //  we will use the two pass MaskBlt()
  319.     //
  320.     //      AND the dest with a DIB that has '1' where the trans color is
  321.     //      '0' otherwise
  322.     //
  323.     //      OR the dest with a DIB that has '0' where the trans color is
  324.     //
  325.  
  326.     rgbBk = GetBkColor(hdc);
  327.  
  328.     if (wUsage == DIB_PAL_COLORS)
  329.     {
  330.     // get current palette.
  331.         hpal = SelectPalette(hdc, (HPALETTE)GetStockObject(DEFAULT_PALETTE), FALSE);
  332.     SelectPalette(hdc, hpal, FALSE);
  333.  
  334.         // get the index of the background color (and black)
  335.         //
  336.         //  NOTE it is *very* important that the palette has
  337.         //  black and white in it (*real* black and white, not
  338.         //  PC_RESERVED or PC_NOCOLAPSE) we are doing raster op's
  339.         //  and assume black==00, and white==FF
  340.         //
  341.         wPalBk    = GetNearestPaletteIndex(hpal, rgbBk);
  342.         wPalBlack = GetNearestPaletteIndex(hpal, rgbBlack);
  343.         wPalWhite = GetNearestPaletteIndex(hpal, rgbWhite);
  344.  
  345.         //
  346.         //  copy the given BITMAPINFO over and munge it, to make our mask.
  347.         //  the usage is DIB_PAL_COLORS so we need to munge index's not
  348.         //  RGBs
  349.        //
  350.         biPal.bih = lpbi->bmiHeader;
  351.         pw = (WORD FAR *)lpbi->bmiColors;
  352.  
  353.         for (i=0; i < (int)biPal.bih.biClrUsed; i++)
  354.         {
  355.             if (pw[i] == wPalBk)
  356.                 biPal.aw[i] = wPalWhite;
  357.             else
  358.                 biPal.aw[i] = wPalBlack;
  359.         }
  360.  
  361.         StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
  362.                           SrcX,SrcY,SrcDX,SrcDY,
  363.                           lpBits, (LPBITMAPINFO)&biPal, wUsage, DSa);
  364.  
  365.         for (i=0; i < (int)biPal.bih.biClrUsed; i++)
  366.         {
  367.             if (pw[i] == wPalBk)
  368.                 biPal.aw[i] = wPalBlack;
  369.             else
  370.                 biPal.aw[i] = pw[i];
  371.  
  372.         }
  373.  
  374.         StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
  375.                           SrcX,SrcY,SrcDX,SrcDY,
  376.                           lpBits, (LPBITMAPINFO)&biPal, wUsage, DSx);
  377.     }
  378.     else
  379.     {
  380.         //  the usage is DIB_RGB_COLORS so we need to munge rgb's not
  381.         //  index's
  382.         //
  383.         biRgb.bih = lpbi->bmiHeader;
  384.         prgb = (DWORD FAR *)lpbi->bmiColors;
  385.  
  386.         for (i=0; i < (int)biPal.bih.biClrUsed; i++)
  387.         {
  388.             if (prgb[i] == RGBQ(rgbBk))
  389.                 biRgb.argb[i] = RGBQ(rgbWhite);
  390.             else
  391.                 biRgb.argb[i] = RGBQ(rgbBlack);
  392.         }
  393.  
  394.         StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
  395.                           SrcX,SrcY,SrcDX,SrcDY,
  396.                           lpBits, (LPBITMAPINFO)&biRgb, wUsage, DSa);
  397.  
  398.         for (i=0; i < (int)biPal.bih.biClrUsed; i++)
  399.         {
  400.             if (prgb[i] == RGBQ(rgbBk))
  401.                 biRgb.argb[i] = RGBQ(rgbBlack);
  402.             else
  403.                 biRgb.argb[i] = prgb[i];
  404.         }
  405.  
  406.         StretchDIBits(hdc,DstX,DstY,DstDX,DstDY,
  407.                           SrcX,SrcY,SrcDX,SrcDY,
  408.                           lpBits, (LPBITMAPINFO)&biPal, wUsage, DSx);
  409.     }
  410.  
  411.     return TRUE;
  412. }
  413.